HELP
Richard Mansfield
Printing This Lesson
Select what you’d like to include when you print, and then click the Print Lesson button:
Text, images and activities (IE users only)
Text and images
Text only
Saving This Lesson
For instructions on saving this lesson (shown below), please select the browser you're using.
Introduction
Hello, and welcome back! In today's lesson, you see how XML uses namespaces to prevent confusion when merging XML documents together into a single document.
Namespaces ensure that CSS, XSL, XSD, and other XML-related files avoid name collisions. What's that? It's when two completely different elements share the same tag name. It's like the first day of school and the teacher says: "Okay, we have three Justins in this class. How should we deal with this?"
Collisions can cause serious misunderstandings. If you stand by the side of the road in America and stick your thumb out, somebody might stop and give you a ride. Do that in Italy, and you could get punched. Same gesture, completely different meanings.
Of course, some words we simply can't misunderstand. XML tags like michelleobama, rockettes, or hopediamond, are so specific and so unambiguous that they just can't collide. They only refer to one thing.
But many words do have multiple meanings. Consider the tag <title>. In the cookbook program, it means one thing, but the same tag would mean something else in British high society or in a real estate office. You can see the problem: There must be a way to specify what kind of <title> we mean.
Element tag name collisions are likely to occur when two companies try to communicate, or merge, their XML data structures.
Ready? Let's get started!
Using Namespaces
XML uses namespaces to distinguish one group of tag names from another. Our recipes.xml tag names are <cookbook>, <recipe>, <title>, and <instructions>. But what if a publisher asks you to send your cookbook XML file for inclusion in a new book that combines several cookbooks. It's more than likely that merging recipes.xml with the other cookbook's XML would result in name collisions.
How does this happen? Most people choose descriptive tag names. After all, that's one of the great advantages of XML! So in pretty much any XML document that holds recipes, you'll find at least some of these tag names: recipe, instructions, ingredients, and directions.
But they might not have identical meanings in different XML files. Think for a minute about the tag instructions. In our cookbook program, we use it to mean the entire recipe—the ingredients and also the directions about how to use those ingredients, all packed into our single instructions element.
Somebody else's XML cookbook might store the ingredients in a separate element, using three elements (title, ingredients, and instructions) where we've used only the two. When the publisher tries to combine our XML data with this other cookbook's XML, they'll have a name collision problem.
Perhaps you've noticed an ns here and there in the declaration code at the top of XML files?
<svg version="1.0" xmlns="http://www.w3.org/2000/svg">
The ns stands for . . . you guessed it, namespace. These lines of code are specifying unique namespaces. Web page addresses like these are unique, so they're a great way to ensure that two namespaces can't be duplicates. Web page addresses are unique for the same reason that your home address is unique. Nobody else lives in the same state, town, street with the same address number.
Here's another namespace example:
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
This code creates a namespace prefix xmlns:inkscape= that you can then use as a shortcut. From now on, in this file's code, the word inkscape will identify this namespace with this unique Web address http://www.inkscape.org/namespaces/inkscape. Using this inkscape prefix, you ensure that it's clear what each tag means.
Here's how it works:
In an SVG document, you would use the namespace prefix followed by a colon. This declares that each of these code lines are Inkscape-specific (they exist within this specific namespace). In this way, there's no doubt that the terms pageshadow and zoom are from the Inkscape set of commands (from the Inkscape namespace):
inkscape:pageshadow="2" inkscape:zoom="0.7"
Let's look at another example, this time from an XSL file.
Here the namespace prefix is called xsl. Then the rest of the XSL document uses that prefix to exclusively identify that its output and template elements are part of this xsl namespace:
Understanding URIs
A URI (Uniform Resource Identifier) is a unique Web address you provide when specifying a namespace. Here's a typical URI:
"http://www.w3.org/2000/svg"
Some URIs aren't Web addresses, but most are. When they are a Web address, URIs are also called URLs (Uniform Resource Locator). You can put the URI in the root element of an XML document (like the xmlns:xsl example above).
When you put the namespace up top in the root element of a document, it becomes the default namespace for the entire document. It's automatically the namespace of all the rest of the elements in the document. The only exception is any elements that specify their own, different URI in an attribute. Here's how to do this—this code uses a URI as an attribute of an individual element:
<myelement xmlns="http://www.MyWebPage/MyNamespace/"> </myelement>
The great thing about using a default namespace in an ordinary XML document is that you eliminate the need to use prefixes. But some documents use multiple namespaces, like this:
<myrootelement xmlns:ohio="http://www.MyWebPage/MyOhioNamespace/" xmlns:utah="http://www.MyWebPage/MyUtahNamespace/">
So in that case, you do have to use prefixes.
All right, let's take a look at mixing namespaces.
Mixing Namespaces
If you need to get really specific, you can sprinkle namespaces all over the place—even using different namespaces for individual lines of code! Look at this XSL code, and notice how the namespace prefixes identify which code lines are XSL and which are not:
<?xml version="1.0" encoding="UTF-8"?> ><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:for-each select="cookbook/recipe"> <tr> <td bgcolor="lightyellow" width="30%"> <xsl:value-of select="title"/> </td> <td> <xsl:value-of select="instructions"/> </td> </tr> </xsl:for-each>
The lines of code with xsl: prefixes are XSL, and the unprefixed <tr> and <td> lines are ordinary HTML. In this way, you can mix and match code lines. Some can have one namespace, others can have a different namespace, and yet others can have no namespace at all. You may never need to use this complex technique—but at least you now know it's available.
Can you think of a situation where you don't need to use namespaces when working with XML?
The primary purpose of XML namespaces is to avoid confusion when different tag naming systems exchange information. <Lancer> to a French fishing supply firm means casting, so there's miscommunication when they send reels to an English boat company that uses <Lancer> to mean a brand of rod.
But if you're using XML for your own, limited, in-house purposes, it's pretty certain the meaning of your tags will be unambiguous. No need to worry about namespaces. We're not using them with the cookbook program!
Using Namespaces in VB
Name collisions aren't limited to XML. They also crop up in various other areas of computing. But namespaces serve a slightly different purpose in programming languages than they do in XML.
The reason is this: Everybody makes up his or her own names for XML tags. But the names of commands in programming languages are made up by the company that created the language—Microsoft in the case of VB. As a result, Microsoft also gets to define the VB namespaces.
So with computer programming languages, namespaces primarily perform the clerical task of organizing the many thousands of commands into separate code libraries (each library is a separate namespace).
What's more, each of these namespaces can in turn contain other namespaces. It's like subcategories in a real-world library . . .
Bringing this idea back to VB . . . take a look at this VB namespace:
System.XML.XPath.
Notice that there are actually three namespaces: System is the primary namespace, but it contains the XML namespace. And XPath is one of the namespaces contained within the XML library. You separate each nested VB namespace with a period.
There are many libraries available to VB—Design, XML, Schema, Web, and dozens of others. VS gives you a choice of various templates when you start a new program. For the cookbook, we chose the Windows Forms Application template. This is the traditional Windows desktop-style application (as opposed to, for example, the new Windows 8 app-type program, or a program designed to run on the Internet).
When we chose the Windows Forms option, VS automatically made available what it considered the necessary code libraries for this kind of application.
Let's take a little tour way down into VB's secret, hidden libraries and see what's there.
A list of default namespaces is revealed. Notice that two of the nine default libraries are dedicated to XML. This reflects the importance of XML in today's computing. But even though XML is a default library, you must still use the Imports command to avoid having to use prefixes in your code.
The term XML in this code is a namespace prefix:
Dim TheCollectionOfTitles As Xml.XmlNodeList
If this were a movie, I'd play some triumphant organ music as you gaze in wonder upon this massive underground storehouse.
Included in the Forms library are all things related to, of course, forms: controls such as the TextBox, and its events like Click or Hide, all its properties like its FontName, and so on. Let's look at some of the descriptions.
A lightning bolt icon represents events, a wrench symbolizes properties, and a box stands for methods.
What Are Members?
In computer programming, we manipulate objects and make use of their features. Objects are everywhere. A button control is one kind of object. But a list of hotels could be an object. You can even create your own objects.
Objects can have three primary features:
Many commands (like End or Save) and controls (such as the Textbox) are in the default VB libraries, so they're built into VB. When an object or control is built in, there are a few things you don't need to worry about:
If the library containing the TextBox control weren't available (referenced automatically), you would need to prefix its namespace like this in your code:
Dim txtBox As System.Windows.Forms.TextBox()
But the TextBox is referenced. It's built into the default Windows forms version of VB, so it automatically loads when VB starts. What does this mean for you? You can leave off the namespace prefix, like this:
Dim txtBox As TextBox
If you need something not in the default namespaces, you can use the Imports command to reference an additional namespace, as we did when we used the Schema namespace in a previous lesson for example.
But there's yet another category: namespaces that the Imports command cannot see!
A namespace like System.Web.Services (used to create code for Web pages) requires that you "reference" it via the Project menu. Why? Because the cookbook program is based on the Windows Forms Application template—it's a traditional desktop application. So it's highly unlikely you're going to want to use a library full of Internet-specific commands. But if for some reason you do, you must add a reference to the Web.Services namespace. The Imports command won't be able to find this library until you first add a reference to it.
In ordinary programming, you may never need to add a reference to a library. The built-in libraries will contain all the commands you need. But if you're going to do some very advanced math, for example, you'll need to add a reference to the Math library.
Let's take a look. Choose Project > Add Reference. You'll see the few namespaces (also known as assemblies or libraries) that are included in VB by default (the checked ones), and you'll see others you can add by clicking (selecting) them. You'll also find a massive set of libraries in the COM list (you can click it on the left side of the Reference Manager dialog box).
Recall that you've used the Imports command in the cookbook code. When writing code that manages schemas, for example, you put this line at the top of the Code window: Imports System.Xml.Schema. Essentially, you're referring to a library of commands called Xml.Schema. You're specifying that namespace.
But it's important to realize that the Imports command is badly misnamed. It doesn't actually import anything. It doesn't add a library of commands to the default VB libraries. In fact, it does only one thing: allows you, the programmer, to use a shortcut—you save a little time by not having to provide the full namespace list in your programming code. You can write ValidationEventHandler in your code, rather than having to write System.Xml.Schema.ValidationEventHandler.
Here's some sample code from the Validator program we wrote in a previous lesson:
Okay, let's simplify things a bit. How do you know when you need to import a code library?
There's a sawtooth line under the ValidationEventHandler command, indicating an error.
If you click the red circle with the white x, a drop-down window provides two excellent suggestions about how to fix this problem:
The error in this code is that VB doesn't understand the underlined command. It's not among the built-in VB commands like Dim or End. Programmers don't use the ValidationEventHandler command very often in desktop application programming (except for us XML programmers).
Notice at the top of the figure that I've used a single-quote to temporarily change this line into a comment. With this, VB will ignore the line and won't recognize this namespace.
'Imports System.Xml.Schema
This "commenting out" debugging technique is useful when you want to see what happens if some code is omitted or is replaced by other code.
Later, I'll need to remove that single quote so VB will actually import the Schema namespace. (Or, alternatively—as VB's error message suggests—I can prefix the ValidationEventHandler command with its namespace, Schema. VB's suggestions on how to fix this error are exactly right.)
To sum up, namespaces in VB serve three purposes:
Letting the User Edit Recipes
Throughout this course, we've added features to the cookbook program—making it easy for the user to search, select, import, and delete recipes. But there's one more major feature we need to provide: editing.
Cooks will often create a dish and then decide that they could improve it—add more onions or whatever. So they want to change the recipe. There's a hard way to do that:
But there's a better solution: Let them make changes directly in the cookbook program.
There's no need for some external text editor. The VB TextBox itself is a text editor. Not only does it display text, the user can change that text. But we programmers do have to write some code to tell the computer what to do when the user changes a recipe's instructions. Our program must update the XML file with the new, modified version of the recipe.
This sounds like an easy programming task. But it turned out to have a few complications I didn't expect. Programmers call complications bugs.
You'll find it helpful to follow the steps I took to get this recipe modification feature working. For one thing, you'll see a programmer in action—the fits and starts, blind alleys, and near misses. And perhaps after seeing me stumble around, you'll be more patient with yourself when your own programming doesn't go smoothly from idea to finished code. Patience and creative thinking are the keys to fixing difficult bugs!
Okay, we're ready to do some XML programming.
We're faced with a classic computer problem in this chapter: When to update the data file?
One solution that even experts recommend surprisingly often is to create a global variable (one that's readable by all events). Let's name it IsDirty. When the user types something into, or clicks, the txtInstructions textbox, you change IsDirty to True. This signals other parts of the program that the user has modified the text and that it's unsaved—so the program needs to update the file:
Private Sub txtInstructions_Click(sender As Object, e As EventArgs) Handles txtInstructions.Click IsDirty = True
How do we know when the user is finished editing? When they leave the textbox by clicking another control, like one of the buttons, to do something else. So first thing in every other control's Click event, you would check to see if the IsDirty variable is set to True. If it is, you would then update the recipes.xml file. After you finish updating, you reset the isDirty variable to False, like this:
But there's a problem with this approach. It's untidy, redundant, complicated, and most of all . . . it stinks.
Making the User Do It
You might be wondering if we can just put another button on the form labeled, "Update the Recipe File." This way, users have to take responsibility for saving a recipe they changed. Isn't this what happens in other software like drawing programs and word processors?
Good points, but our program isn't exactly like a word processor where you're constantly creating new text or editing. The cookbook is mostly for searching and displaying recipes. Modifying them is likely to be relatively uncommon.
But the main reason to have the program update the data rather than the user is that it's the more elegant approach. After all, the user might forget to click that update button. If they only modified one recipe, they'd be annoyed if it didn't save. But what if they typed in dozens of recipes and lost all that data? They'd probably be distraught!
So let's try to find a way to update the data file automatically.
Choosing an Event
In this course, you've learned that you can put VB programming inside events (subs), because VB usually executes a block of code in response to something the user does: KeyPress, Click, TextChanged, and dozens of other events.
So our first step is to figure out in which event to put the code that updates the recipes.xml file. Remember, we're trying to avoid putting it in every event like the previous example that uses an IsDirty variable. Can we find just one event that always triggers when the user finishes modifying a recipe?
We should probably use a textbox event. Just a simple event that happens to the textbox itself.
Okay, watch this series of screen recordings as I try to figure this out. And if you have any questions as you watch, just press Pause and head over to the Discussion Area.
The three videos in this lesson illustrate what happens when a programmer, me in this case, struggles to solve a difficult problem. Namely, a tough bug. Fortunately, they're not that common. Most of them don't take this long to solve, but I want you to get a feel for what it takes to hack away and track down a bad problem. And let me remind you, you don't need to understand fully all this code, and you certainly aren't expected to memorize it at this point in your career. You merely need to watch as I wrestle this thing.
We want to figure out how to update a recipe. The user is allowed to make changes to any instructions in any recipe that they want to. The question is: when do we update the file on the hard drive in our programming? What event should save this recipe change? It seemed pretty clear that the textbox itself that contains the changed instructions should have an event that does the updating, but which event?
So let's choose the textbox here in this drop-down list, and then over here we'll show all the events that are available to a textbox. And at first I thought maybe the best thing to do would be to put our updating code in the TextChanged event. TextChanged looks promising. It triggers whenever the text is changed, and so I thought, "Well, that makes sense."
But then I realized that pretty much everything that happens in the Cookbook program triggers this event over and over again. If you click the Delete key, or you Show All the Titles, or you Import a recipe—any of those buttons will change the displayed instructions and thus trigger this TextChanged event. Even though the user hasn't modified the recipe, the Delete button, for example, changes this instruction—the instructions shown. The program is constantly overwriting the recipes.xml file if you put in some code here in this TextChanged event to save to the file.
How did I find that out? Well, I tried putting a message box inside here to see what would happen. Then I ran the program and did various things, and I realized that this message box was popping up constantly for almost anything that happened in the program. And even worse, the TextChanged responds hysterically while the user is modifying a recipe, triggering for every key the user presses.
So, what if he or she typed in a 150-word-long paragraph? The hard drive would be grinding away, updating the recipes.xml file on the hard drive over and over again for every key pressed. Now, that won't turn the computer into a space heater, but the words "hyper" and "impractical" do come to mind. So let's go back up to the top and pick a different event, one that might not be quite so hyper.
How about the KeyPress event? That sounds promising. At least this will trigger only when the user is typing. It won't be triggered by other events in the program, like clicking the Delete button. Only by key presses. And although it sounds reasonable to use this, by using the message box again, I found out that, yep, KeyPress, too, triggers every single time a user presses a key.
Realizing then that this really wasn't as trivial a problem as I had first thought, I relaxed a little and I slowed down enough to ask myself the right questions. And if you'll click on the next video, I'll show you the questions that I asked
END TRANSCRIPT
So let's back up a little bit the way I did and stop for a minute and just ask ourselves: what exactly do we want to do? When do we want to save this recipe that the users edited? And the answer is we want to save it exactly the moment that the user finishes editing that recipe.
Now, how do I know in the programming when the user has finished editing? And the answer to that is it's when the user leaves this text instruction textbox. When he or she starts doing something other than typing instructions in this textbox. When they click a button, or they start a search, or they even shut down the program—any of those things are not typing in this textbox. So I want to find out when the user leaves this box. And the answer comes to me, finally, if I look over here in the possible events for a textbox. There's lots of events, but there is one here that says Leave, so let's give that a try.
There is a Leave event. "Perfect," I thought. "This is it." This makes Visual Basic do all the heavy lifting. It has to watch what the user is doing, and then trigger this Leave event when the user moves on to some other task. No need for me to write code that checks global variables at the start of all my subroutines, and no need to repeatedly update the XML file on the hard drive every time the user simply presses one key. This finally seemed like the clean solution, and here's the code that I put into the Leave event to do the updating.
I thought I was home free. Finally, this is going to work. But, no. I was so happy to find this Leave event that I started just to relax and think about lunch. But bugs can pop up when you least expect them. I started modifying a few recipes to make sure everything was working right and to test this code, and then the bug showed itself. It was a minor bug in the sense that its effects were not catastrophic for the user. The program didn't crash and there was no damage to the data itself, but it took a long time for me to track this down and fix it.
This brings up the question, should you spend hours fixing a minor bug? Well, it's always up to you. If the program is just for your own use and the bug's fairly insignificant, maybe you can just tolerate it, work around it, deal with it, put up with it. But you probably want to polish programs if you're going to share them with others, and you certainly have to polish them, get rid of bugs, when you write professional code.
This Leave event does everything right except one thing. If you finish modifying a recipe and then decide to go and look at a different recipe, there's a bug. You would click the new recipe's title in the list box, and, unfortunately, when you do that after editing in the textbox, when you make the click to go to look at another title, nothing happens. Normally, the minute you click a recipe's title in that list box, that title's instructions show up in the text instructions textbox so you see the whole recipe. But the Leave event prevents this from happening, and I couldn't figure out why.
When you click to see a title, all you see is the instructions for the recipe you just modified, not the instructions for the new recipe you just clicked. This is a discontinuity. The title now selected, that's highlighted in that list box, doesn't match the instructions displayed over here in our textbox. Users would become confused or annoyed, but we really can't blame this problem on the Leave event itself. And so I spent hours trying the different things to discover what this problem was, why the list box wasn't being updated. I'll tell you the solution in the next video
Let me show you how the bug looks. When I press F5 to run the program, I'll go over here, and I'll delete something from the Beef Tips recipe. Now, when I click the Coleslaw recipe, it should show up, but it doesn't. We're still seeing the Beef recipe over here, and that's our bug.
So I did some debugging and single-stepping to see if I could figure out what was happening, and it turned out that the program wasn't updating the list box's selected item property. And this is VB's fault. It seems that in this rare situation, when the user clicks a title in the list box, the list box doesn't get the message. It doesn't know that the user has clicked.
So let's go up here to the list box Click event and see if we can figure out what's going on. One good debugging technique is to simply temporarily insert a message box, and then when you run the program, you can see the contents of a variable. And in this case, we'll see what's the selected item when we run it. And although this is a debugging technique, for some reason this solved the problem. The bug went away. Was I surprised. So I went to lunch. I needed a break.
How does simply pausing this program's execution to display this message box update the selected item property? Why? This is one reason that people often describe programming as half science and half art. The art part includes lurching around and hacking, like I'm doing, until you finally discover its weird solution to an equally weird problem.
But clearly this isn't a real solution because we can't leave a message box debugging technique in the middle of the code. When the user runs it, they won't stand for it. They'd be mystified by a message box constantly appearing. What purpose does it serve? It doesn't for them. It's a debugging technique.
So I thought, "Maybe it's the pause. Maybe it's the fact that VB has to pause here." So I replaced this message box with a pause. The VB Sleep command simply stops execution for whatever amount of time you specify. It works with milliseconds, so 2,000 would be a two second delay. That dead-paused the program, but it didn't solve the bug.
So I then tried a Do events command which, in VB, slows down the program to let other events execute, such as dragging a window while VB is doing something. And this multitasking effect didn't work either. It was just another blind alley.
Then I thought maybe it's not the delay itself, but just the fact that some code, any code, is executing between when the user clicks and the property gets updated. So I tried using the list box's Refresh command. Nothing. Another blind alley. But unbeknownst to me, I was getting closer. You bang on enough doors, one of them probably will open.
Finally, I got the right answer. I tried switching the focus to another object on the form. In this case, I thought I'd try the txtSearch textbox. So I used the Select command to put the focus on the txtSearch. That worked. This was the solution. It won't bother the user. They won't care that the focus has shifted, and it does somehow fix this bug.
Can I explain why this fixes the bug? No. Does it work reliably? Yes. So I don't actually care to know the sordid technical details about what is really not my bug, but Visual Basic's
This, finally, seemed the clean solution. In the classroom, I've included the code that I put into the Leave event to do the updating.
Code in the Leave Event
Let's Chat!
How do you feel about testing and debugging? Do you find it tedious and annoying? Or is it more like a puzzle that's fun to solve? Visit the Discussion Area to discuss with your classmates.
Summary
Great work! This lesson covered namespaces. You learned that their primary purpose in XML is to ensure that identical tag names referring to different content don't cause confusion when merging XML documents. And you now know that their main purpose in VB or other programming languages is to organize related commands into sets of code libraries.
You also know how to add the final feature to the cookbook program: allowing the user to edit recipes and having the program automatically update the recipes.xml file with your changes. You saw how fixing bugs can be challenging (and even frustrating at times), but you also saw that bugs can offer a puzzle that's fun to solve!
Think you've got the hang of namespaces? Try out this quick game and see how you do!
Mountaineer Game
In the next lesson, you'll create two new VB programs. I'll see you when you're ready!
If you're still a bit fuzzy about what the Imports command does in VB, here's a good tutorial. This site offers a variety of other useful VB tips and articles too.
Here's a good site to visit if you want to see examples of color numbers, shades, and complementary colors.
Q: Can you use namespaces with attributes too?
A: It's not illegal to add a namespace prefix to attributes, but it's hardly ever necessary. That's because attributes are rarely ambiguous—they're contained within an element. Think of it this way: An attribute automatically inherits the namespace of its element, just as your house cat automatically shares your address.
Users almost always like feedback—and they typically want to know if something has changed. For today's assignment, I want you to add a color cue that tells the users the program has saved their editing after they've finished editing it.
You can do this by changing the txtInstructions textbox's BackColor. Its current BackColor is 255, 224, 192, a tan. How about changing the BackColor to white if the user starts modifying the text? Then change it back to tan after the program saves the changes.
Here are the code lines you'll want to put into the proper places in the program. Figure out in which events you should insert them.
Here's the line to turn the textbox white:
txtInstructions.BackColor = Color.FromArgb(255,255,255)
And the one to turn it back to tan:
txtInstructions.BackColor = Color.FromArgb(255, 224, 192)
This was a tough assignment, so if you got it even half right, congratulations. And if you got it totally right, bravo!
Back to top